package com.ngis.udx;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.ngis.udxschema.ESchemaNodeType;

public class UdxDataset extends UdxNode
{
	public UdxDataset()
	{
		super(null, "", EKernelType.EKT_NODE);
		mName = "dataset";
	}
	
	@Override
	public void finalize()
	{
	}
	
	public boolean LoadFromXmlFile(String fileName)
	{
		try
        {
	        SAXReader reader = new SAXReader();
	        Document doc;
			doc = reader.read(new File(fileName));
	
	        Element rootEle = doc.getRootElement();	     

            int count = rootEle.elements().size();
            for (int i = 0; i < count; i++)
            {
                Element ele = rootEle.elements().get(i);
                ParseXDO((UdxNode)this, ele);
            }
            return true;
        }
        catch (Exception ex)
        {

        }
        return false;
	}

	public boolean FormatToXmlFile(String fileName)
	{
		try
        {
	        Document doc = DocumentHelper.createDocument();
            Element element = doc.addElement("dataset");

            int count = this.getChildNodeCount();
            for (int iNode = 0; iNode < count; iNode++)
            {
                UdxNode tempNode = this.getChildNode(iNode);
                FormatXDO(tempNode, element);
            }
            
            OutputFormat format = new OutputFormat();
            format.setEncoding("UTF-8");
		    XMLWriter writer;
			writer = new XMLWriter(new FileWriter(fileName), format);
		    writer.write(doc);
		    writer.close();
		    return true;
        }
        catch (Exception ex)
        {

        }
        return false;
	}
	
	public boolean LoadFromXmlStream(String xml_str)
	{
		try
        {
	        Document doc;
			doc = DocumentHelper.parseText(xml_str);
		    Element rootEle = doc.getDocument().getRootElement();
		    
            int count = rootEle.elements().size();
            for (int i = 0; i < count; i++)
            {
                Element ele = rootEle.elements().get(i);
                ParseXDO((UdxNode)this, ele);
            }
            return true;
        }
        catch (Exception ex)
        {

        }
        return false;
	}

	public String FormatToXmlStream()
	{
		String xml_str = "";
        try
        {
            Document doc = DocumentHelper.createDocument();
            Element element = doc.addElement("dataset");

            int count = this.getChildNodeCount();
            for (int iNode = 0; iNode < count; iNode++)
            {
                UdxNode tempNode = this.getChildNode(iNode);
                FormatXDO(tempNode, element);
            }

            xml_str = doc.asXML();
        }
        catch (Exception ex)
        {
        	
        }
        return xml_str;
	}
	
	String KernelType2String(EKernelType pType) 
	{
		if (pType == EKernelType.EKT_INT) 
			return "int";
		else if (pType == EKernelType.EKT_REAL) 
			return "real";
		else if (pType == EKernelType.EKT_STRING) 
			return "string";
		else if (pType == EKernelType.EKT_VECTOR2) 
			return "vector2d";
		else if (pType == EKernelType.EKT_VECTOR3) 
			return "vector3d";
		else if (pType == EKernelType.EKT_VECTOR4) 
			return "vector4d";
		else if (pType == EKernelType.EKT_INT_LIST)
			return "int_array";
		else if (pType == EKernelType.EKT_REAL_LIST)
			return "real_array";
		else if (pType == EKernelType.EKT_STRING_LIST)
			return "string_array";
		else if (pType == EKernelType.EKT_VECTOR2_LIST)
			return "vector2d_array";
		else if (pType == EKernelType.EKT_VECTOR3_LIST)
			return "vector3d_array";
		else if (pType == EKernelType.EKT_VECTOR4_LIST)
			return "vector4d_array";
		else if (pType == EKernelType.EKT_NODE)
			return "any";
		else if (pType == EKernelType.EKT_LIST)
			return "list";
		else if (pType == EKernelType.EKT_MAP)
			return "map";
		else if (pType == EKernelType.EKT_TABLE)
			return "table";
		else
			return "any";
	}
	
	EKernelType String2KernelType(String pStr)
	{
		if (pStr.equals("int"))
			return EKernelType.EKT_INT;
		else if (pStr.equals("real"))
			return EKernelType.EKT_REAL;
		else if (pStr.equals("string"))
			return EKernelType.EKT_STRING;
		else if (pStr.equals("vector2d"))
			return EKernelType.EKT_VECTOR2;
		else if (pStr.equals("vector3d"))
			return EKernelType.EKT_VECTOR3;
		else if (pStr.equals("vector4d"))
			return EKernelType.EKT_VECTOR4;
		else if (pStr.equals("int_array"))
			return EKernelType.EKT_INT;
		else if (pStr.equals("real_array"))
			return EKernelType.EKT_REAL;
		else if (pStr.equals("string_array"))
			return EKernelType.EKT_STRING;
		else if (pStr.equals("vector2d_array"))
			return EKernelType.EKT_VECTOR2;
		else if (pStr.equals("vector3d_array"))
			return EKernelType.EKT_VECTOR3;
		else if (pStr.equals("vector4d_array"))
			return EKernelType.EKT_VECTOR4;
		else if (pStr.equals("any"))
			return EKernelType.EKT_NODE;
		else if (pStr.equals("list"))
			return EKernelType.EKT_LIST;
		else if (pStr.equals("map"))
			return EKernelType.EKT_MAP;
		else if (pStr.equals("table"))
			return EKernelType.EKT_TABLE;
		return null;
	}


    void ParseXDO(UdxNode containerNode, Element element)
    {
        String typeStr = element.attributeValue("kernelType");
        String name = element.attributeValue("name");
        EKernelType kernelType = String2KernelType(typeStr);

        if (typeStr == "int")
        {
            int val = Integer.parseInt(element.attributeValue("value"));
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelIntValue realKernel = (UdxKernelIntValue)node.getKernel();
            realKernel.setTypedValue(val);
        }
        else if (typeStr == "real")
        {
            double val = Double.parseDouble(element.attributeValue("value"));
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelRealValue realKernel = (UdxKernelRealValue)node.getKernel();
            realKernel.setTypedValue(val);
        }
        else if (typeStr == "String")
        {
            String val = element.attributeValue("value");
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelStringValue realKernel = (UdxKernelStringValue)node.getKernel();
            realKernel.setTypedValue(val);
        }
        else if (typeStr == "vector2d")
        {
            String valStr = element.attributeValue("value");
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelVector2dValue realKernel = (UdxKernelVector2dValue)node.getKernel();
            double x, y;
            String[] ret = valStr.split(",");
            x = Double.parseDouble(ret[0]);
            y = Double.parseDouble(ret[1]);
            realKernel.setTypedValue(x, y);
        }
        else if (typeStr == "vector3d")
        {
            String valStr = element.attributeValue("value");
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelVector3dValue realKernel = (UdxKernelVector3dValue)node.getKernel();
            double x, y, z;
            String[] ret = valStr.split(",");
            x = Double.parseDouble(ret[0]);
            y = Double.parseDouble(ret[1]);
            z = Double.parseDouble(ret[2]);
            realKernel.setTypedValue(x, y, z);
        }
        else if (typeStr == "vector4d")
        {
            String valStr = element.attributeValue("value");
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelVector4dValue realKernel = (UdxKernelVector4dValue)node.getKernel();
            double x, y, z, m;
            String[] ret = valStr.split(",");
            x = Double.parseDouble(ret[0]);
            y = Double.parseDouble(ret[1]);
            z = Double.parseDouble(ret[2]);
            m = Double.parseDouble(ret[3]);
            realKernel.setTypedValue(x, y, z, m);
        }
        else if (typeStr == "int_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(",");
            int count = ret.length;
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelIntArray realKernel = (UdxKernelIntArray)node.getKernel();
            for (int iVal = 0; iVal < count; iVal++)
            {
                realKernel.addTypedValue(Integer.parseInt(ret[iVal]));
            }
        }
        else if (typeStr == "real_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(",");
            int count = ret.length;
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelRealArray realKernel = (UdxKernelRealArray)node.getKernel();
            for (int iVal = 0; iVal < count; iVal++)
            {
                realKernel.addTypedValue(Double.parseDouble(ret[iVal]));
            }
        }
        else if (typeStr == "string_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(";");
            int count = ret.length;
            UdxNode node = containerNode.addChildNode(name, kernelType);
            UdxKernelStringArray realKernel = (UdxKernelStringArray)node.getKernel();
            for (int iVal = 0; iVal < count; iVal++)
            {
                realKernel.addTypedValue(ret[iVal]);
            }
        }
        else if (typeStr == "vector2d_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(";");
            int count = ret.length;
            {
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector2dArray realKernel = (UdxKernelVector2dArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    double x, y;
                    String[] ret1 = ret[iVal].split(",");
                    x = Double.parseDouble(ret1[0]);
                    y = Double.parseDouble(ret1[1]);
                    realKernel.addTypedValue(x, y);
                }
            }
        }
        else if (typeStr == "vector3d_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(";");
            int count = ret.length;
            {
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector3dArray realKernel = (UdxKernelVector3dArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    double x, y, z;
                    String[] ret1 = ret[iVal].split(",");
                    x = Double.parseDouble(ret1[0]);
                    y = Double.parseDouble(ret1[1]);
                    z = Double.parseDouble(ret1[2]);
                    realKernel.addTypedValue(x, y, z);
                }
            }
        }
        else if (typeStr == "vector4d_array")
        {
            String valStr = element.attributeValue("value");
            String[] ret = valStr.split(";");
            int count = ret.length;
            {
                UdxNode node = containerNode.addChildNode(name, kernelType);
                UdxKernelVector4dArray realKernel = (UdxKernelVector4dArray)node.getKernel();
                for (int iVal = 0; iVal < count; iVal++)
                {
                    double x, y, z, m;
                    String[] ret1 = ret[iVal].split(",");
                    x = Double.parseDouble(ret1[0]);
                    y = Double.parseDouble(ret1[1]);
                    z = Double.parseDouble(ret1[2]);
                    m = Double.parseDouble(ret1[3]);
                    realKernel.addTypedValue(x, y, z, m);
                }
            }
        }
        else if (typeStr == "any" ||
                  typeStr == "list" ||
                  typeStr == "map" ||
                  typeStr == "table")
        {
            UdxNode node = containerNode.addChildNode(name, kernelType);
            int ele_count = element.elements().size();
            for (int iChild = 0; iChild < ele_count; iChild++)
            {
                Element childEle = (Element)element.elements().get(iChild);
                ParseXDO(node, childEle);
            }
        }

    }

    void FormatXDO(UdxNode pNode, Element element)
    {
        EKernelType kernelType = pNode.getKernel().getType();
        String name = pNode.getName();
        Element childEle = element.addElement("XDO");
        childEle.addAttribute("name", name);
        if (kernelType == EKernelType.EKT_INT)
        {
            UdxKernelIntValue realKernel = (UdxKernelIntValue)pNode.getKernel();
            int val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", String.valueOf(val));
        }
        else if (kernelType == EKernelType.EKT_REAL)
        {
            UdxKernelRealValue realKernel = (UdxKernelRealValue)pNode.getKernel();
            double val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", String.valueOf(val));
        }
        else if (kernelType == EKernelType.EKT_STRING)
        {
            UdxKernelStringValue realKernel = (UdxKernelStringValue)pNode.getKernel();
            String val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", val);
        }
        else if (kernelType == EKernelType.EKT_VECTOR2)
        {
            UdxKernelVector2dValue realKernel = (UdxKernelVector2dValue)pNode.getKernel();
            Vector2d val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", String.valueOf(val.x) + "," + String.valueOf(val.y));
        }
        else if (kernelType == EKernelType.EKT_VECTOR3)
        {
            UdxKernelVector3dValue realKernel = (UdxKernelVector3dValue)pNode.getKernel();
            Vector3d val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", String.valueOf(val.x) + "," + String.valueOf(val.y) + "," + String.valueOf(val.z));
        }
        else if (kernelType == EKernelType.EKT_VECTOR4)
        {
            UdxKernelVector4dValue realKernel = (UdxKernelVector4dValue)pNode.getKernel();
            Vector4d val = realKernel.getTypedValue();
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", String.valueOf(val.x) + "," + String.valueOf(val.y) + "," + String.valueOf(val.z) + "," + String.valueOf(val.m));
        }
        else if (kernelType == EKernelType.EKT_INT_LIST)
        {
            UdxKernelIntArray realKernel = (UdxKernelIntArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                if (iVal != count - 1)
                    valStr += String.valueOf(realKernel.getTypedValueByIndex(iVal)) + ", ";
                else
                    valStr += String.valueOf(realKernel.getTypedValueByIndex(iVal));
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_REAL_LIST)
        {
            UdxKernelRealArray realKernel = (UdxKernelRealArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                if (iVal != count - 1)
                    valStr += String.valueOf(realKernel.getTypedValueByIndex(iVal)) + ", ";
                else
                    valStr += String.valueOf(realKernel.getTypedValueByIndex(iVal));
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_STRING_LIST)
        {
            UdxKernelStringArray realKernel = (UdxKernelStringArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                if (iVal != count - 1)
                    valStr += realKernel.getTypedValueByIndex(iVal) + ", ";
                else
                    valStr += realKernel.getTypedValueByIndex(iVal);
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_VECTOR2_LIST)
        {
            UdxKernelVector2dArray realKernel = (UdxKernelVector2dArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                Vector2d temp_val = realKernel.getTypedValueByIndex(iVal);
                if (iVal != count - 1)
                    valStr += temp_val.x + "," + temp_val.y + "; ";
                else
                    valStr += temp_val.x + "," + temp_val.y;
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_VECTOR3_LIST)
        {
            UdxKernelVector3dArray realKernel = (UdxKernelVector3dArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                Vector3d temp_val = realKernel.getTypedValueByIndex(iVal);
                if (iVal != count - 1)
                    valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "; ";
                else
                    valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z;
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_VECTOR4_LIST)
        {
            UdxKernelVector4dArray realKernel = (UdxKernelVector4dArray)pNode.getKernel();
            String valStr = "";
            int count = realKernel.getCount();
            for (int iVal = 0; iVal < count; iVal++)
            {
                Vector4d temp_val = realKernel.getTypedValueByIndex(iVal);
                if (iVal != count - 1)
                    valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "," + temp_val.m + "; ";
                else
                    valStr += temp_val.x + "," + temp_val.y + "," + temp_val.z + "," + temp_val.m;
            }
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            childEle.addAttribute("value", valStr);
        }
        else if (kernelType == EKernelType.EKT_NODE ||
                   kernelType == EKernelType.EKT_LIST ||
                   kernelType == EKernelType.EKT_MAP ||
                   kernelType == EKernelType.EKT_TABLE)
        {
            childEle.addAttribute("kernelType", KernelType2String(kernelType));
            int count = pNode.getChildNodeCount();
            for (int iNode = 0; iNode < count; iNode++)
            {
                UdxNode tempNode = pNode.getChildNode(iNode);
                FormatXDO(tempNode, childEle);
            }
        }
    }

}
